<template>
	<view class="amap-container">
		<!-- #ifdef APP-VUE || H5 -->
		<view
			id="amap"
			:prop="renderData" 
			:change:prop="amap.updateProps" 
			:style="[mapStyle, customStyle]"
		></view>
		<!-- #endif -->
		<!-- #ifdef MP-WEIXIN -->
		<map
			id="amap"
			:style="[mapStyle, customStyle]"
			:longitude="mapCenter[0]"
			:latitude="mapCenter[1]"
			:markers="wxMarkers"
			:polygons="wxPolygons"
			:polyline="wxPolylines"
			:show-location="showLocation"
			:subkey="subkeyWx"
			:scale="scale"
			@markertap="markertap"
			@labeltap="labeltap"
			@tap="mapTap"
		></map>
		<!-- #endif -->
	</view>
</template>

<script>
	export default {
		props: {
			// 自定义地图样式
			customStyle: {
				type: Object,
				default: () => ({})
			},
			// 地图key
			mapkey: {
				type: String,
				default: ''
			},
			// wx个性化地图key
			subkeyWx: {
				type: String,
				default: ''
			},
			// h5个性化地图key
			subkeyH5: {
				type: String,
				default: ''
			},
			scale: {
				type: Number,
				default: 17
			},
			mapCenter: {
				type: Array,
				default: () => [0, 0]
			},
			// 显示当前定位的箭头
			showLocation: {
				type: Boolean,
				default: true
			},
			// 缩放视野展示所有的坐标点
			includePoints: {
				type: Array,
				default: () => []
			},
			padding: {
				type: Array,
				default: () => [20, 20, 20, 20]
			},
			markerList: {
				type: Array,
				default: () => []
			},
			labelList: {
				type: Array,
				default: () => []
			},
			polygonList: {
				type: Array,
				default: () => []
			},
			polylineList: {
				type: Array,
				default: () => []
			}
		},
		data() {
			return {
				mapStyle: {
					width: '100vw',
					height: '100vh',
					transition: 'height .3s ease'
				}
			}
		},
		watch: {
			// #ifdef MP-WEIXIN
			mapCenter: {
				handler(newValue, oldValue) {
					console.log('加载完成')
					this.$emit('mapComplete')
					
					let map = wx.createMapContext('amap', this);
					if (this.includePoints.length > 0) {
						map.includePoints({
							points: this.includePoints,
							padding: this.padding
						})
					}
					
					// console.log(map)
					// map.addGroundOverlay({
					// 	id: 123,
					// 	src: '/static/logo.png',
					// 	bounds: {
					// 		southwest: {
					// 			longitude: 113.798391,
					// 			latitude: 34.764399
					// 		},
					// 		northeast: {
					// 			longitude: 113.806717,
					// 			latitude: 34.77011
					// 		}
					// 	},
					// 	success: res => {
					// 		console.log(res)
					// 	},
					// 	fail: res => {
					// 		console.log(res)
					// 	}
					// })
				}
			},
			// #endif
		},
		computed: {
			// #ifdef APP-VUE || H5
			renderData() {
				return JSON.parse(JSON.stringify({
					config: {
						mapkey: this.mapkey,
						subkey: this.subkeyH5,
						scale: this.scale
					},
					mapCenter: this.mapCenter,
					markerList: this.markerList,
					labelList: this.labelList,
					polygonList: this.polygonList,
				}))
			}
			// #endif
			
			// #ifdef MP-WEIXIN
			wxMarkers() {
				return this.markerList.map((item, index) => ({
					id: index,
					longitude: item.position.longitude,
					latitude: item.position.latitude,
					iconPath: item.iconPath,
					width: item.size[0],
					height: item.size[1],
					label: this.labelList.length > 0 ? {
						content: this.labelList[index].content,
						color: '#FFFFFF',
						bgColor: this.labelList[index].bgColor,
						color: this.labelList[index].color,
						padding: uni.upx2px(15),
						fontSize: uni.upx2px(30),
						borderRadius: 4,
						textAlign: 'center'
					} : null
				}))
			},
			wxPolygons() {
				return this.polygonList.map(item => ({
					points: item.points,
					strokeWidth: 2,
					strokeColor: item.color,
					fillColor: item.color + '38'
				}))
			},
			wxPolylines() {
				return this.polylineList.map(item => ({
					points: item.points,
					color: item.color,
					width: 5,
					dottedLine: item.dottedLine
				}))
			}
			// #endif
		},
		methods: {
			// #ifdef APP-VUE || H5
			//地图点击回调事件
			onViewClick(params) {
				this.$emit('itemClick', params)
			},
			mapComplete() {
				console.log('加载完成')
				this.$emit('mapComplete')
			}
			// #endif
			
			// #ifdef MP-WEIXIN
			// marker点击回调
			markertap(e) {
				// console.log(e)
				this.$emit('itemClick', {
					type: 'marker',
					index: e.detail.markerId
				})
			},
			labeltap(e) {
				this.$emit('itemClick', {
					type: 'label',
					index: e.detail.markerId
				})
			},
			mapTap(e) {
				// console.log(e)
				this.$emit('itemClick', {
					type: 'map'
				})
			}
			// #endif
		}
	}
</script>

<script module="amap" lang="renderjs">
	export default {
		data() {
			return {
				map: null,
				markers: [], // 存放图标覆盖物
				labels: [], // 存放文字覆盖物
				polygons: [], // 存放多边形
				ownerInstanceObj: null //service层对象
			}
		},
		methods: {
			init(center, config) {
				if (typeof window.AMap === 'function') {
					this.initAmap(center, config)
				} else {
					// 动态引入较大类库避免影响页面展示
					const script = document.createElement('script')
					script.src = `https://webapi.amap.com/maps?v=2.0&key=${config.mapkey}`
					script.onload = () => {
						this.initAmap(center, config)
					}
					document.head.appendChild(script)
				}
			},
			// 初始化地图
			initAmap(center, config) {
				if (!this.map) {
					this.map = new AMap.Map('amap', {
						resizeEnable: true,
						center: center,
						zooms: [3, 20], //设置地图级别范围
						zoom: config.scale,
						mapStyle: config.subkey
					})
					// 地图加载完成事件
					this.map.on('complete', (e) => {
						this.ownerInstanceObj.callMethod('mapComplete')
					});
					this.map.on('click', (e) => {
						this.ownerInstanceObj.callMethod('onViewClick', {
							type: 'map'
						})
					});
				} else {
					this.map.setCenter(center);
				}
			},
			// 创建图标覆盖物
			createMarkers(listObj) {
				let removes = [];
				listObj.minus.forEach(item => {
					let diff = this.markers.filter(item1 => item1.getExtData() == item.id);
					if (diff.length > 0) {
						removes.push(diff[0]);
					}
					this.markers = this.markers.filter(item1 => item1.getExtData() != item.id);
				})
				listObj.plus.forEach((item, index) => {
					let currentIndex = listObj.origin.map(e => e.id).indexOf(item.id);
					let marker = new AMap.Marker({
						position: [item.position.longitude, item.position.latitude],
						icon: new AMap.Icon({
							imageSize: item.size,
							size: item.size,
							image: item.iconPath.replace(/^\//, '') 
						}),
						anchor: item.anchor || 'bottom-center',
						offset: new AMap.Pixel(0, 0),
						extData: item.id,
						zIndex: item.zIndex || 10
					});
					marker.on('click', () => {
						
						this.onClick({
							type: 'marker',
							index: currentIndex
						})
					})
					this.map.add(marker);
					this.markers.push(marker);
				})
				setTimeout(() => {
					this.map.remove(removes);
				}, 30)
			},
			// 创建文字覆盖物
			createLabels(listObj) {
				let removes = [];
				listObj.minus.forEach(item => {
					let diff = this.labels.filter(item1 => item1.getExtData() == item.id);
					if (diff.length > 0) {
						removes.push(diff[0]);
					}
					this.labels = this.labels.filter(item1 => item1.getExtData() != item.id);
				})
				listObj.plus.forEach((item, index) => {
					let currentIndex = listObj.origin.map(e => e.id).indexOf(item.id);
					let markerContent = `<div style="
						box-sizing: border-box;
						padding: ${uni.upx2px(15)}px ${uni.upx2px(20)}px;
						background: ${item.bgColor};
						color: ${item.color};
						line-height: 1.2;
						border-radius: ${uni.upx2px(4)}px;
						position: relative;
						width: auto;
						box-shadow: 0px 0px 4px 0px ${item.bgColor};
						font-size: ${uni.upx2px(30)}px;
						word-break: keep-all;
					">
						${item.content}
						<div style="
							content: '';
							position: absolute;
							height: 0;
							width: 0;
							border: ${uni.upx2px(8)}px solid transparent;
							border-top-color: ${item.bgColor};
							bottom: -${uni.upx2px(16)}px;
							left: 50%;
							transform: translateX(-50%);
						"></div>
					</div>`;
					let label = new AMap.Marker({
						position: [item.position.longitude, item.position.latitude],
						content: markerContent,
						anchor: 'bottom-center',
						offset: new AMap.Pixel(0, uni.upx2px(-8)),
						extData: item.id,
						zIndex: item.zIndex || 100
					});
					label.on('click', () => {
						this.onClick({
							type: 'label',
							index: currentIndex
						})
					})
					this.map.add(label);
					this.labels.push(label);
				})
				setTimeout(() => {
					this.map.remove(removes);
				}, 30)
			},
			// 创建多边形覆盖物
			createPolygons(listObj) {
				let removes = [];
				listObj.minus.forEach(item => {
					let diff = this.polygons.filter(item1 => item1.getExtData() == item.id);
					if (diff.length > 0) {
						removes.push(diff[0]);
					}
					this.polygons = this.polygons.filter(item1 => item1.getExtData() != item.id);
				})
				listObj.plus.forEach((item, index) => {
					let currentIndex = listObj.origin.map(e => e.id).indexOf(item.id);
					let polygon = new AMap.Polygon({
						strokeWeight: 2,
						strokeOpacity: 1,
						fillOpacity: 0.2,
						strokeStyle: 'solid',
						path: item.points.map(
							e => new AMap.LngLat(e.longitude, e.latitude)
						),
						strokeColor: item.color,
						fillColor: item.color,
						extData: item.id,
						zIndex: item.zIndex || 1
					});
					polygon.on('click', () => {
						this.onClick({
							type: 'polygon',
							index: currentIndex
						})
					})
					this.map.add(polygon);
					this.polygons.push(polygon);
				})
				setTimeout(() => {
					this.map.remove(removes);
				}, 30)
			},
			updateProps(newValue, oldValue, ownerInstance, instance) {
				console.log('数据更新了')
				this.compareParams(newValue, oldValue)
				// 监听 service 层数据变更
				this.ownerInstanceObj = ownerInstance
			},
			// 比较数据变化，执行相应方法
			compareParams(newValue, oldValue) {
				for (let key in newValue) {
					if (JSON.stringify(newValue[key]) != JSON.stringify(oldValue[key])) {
						switch (key) {
							case 'mapCenter':
								this.init(newValue.mapCenter, newValue.config);
								break;
							case 'polygonList':
								this.createPolygons(this.findDiff(newValue[key], oldValue[key]));
								break;
							case 'markerList':
								this.createMarkers(this.findDiff(newValue[key], oldValue[key]));
								break;
							case 'labelList':
								this.createLabels(this.findDiff(newValue[key], oldValue[key]));
								break;
						}
					}
				}
				if (this.map) this.map.setFitView();
			},
			// 找出new相对于old减少的项和增加的项
			findDiff(newValue, oldValue) {
				let newStrArr = newValue.map(item => JSON.stringify(item));
				let oldStrArr = oldValue.map(item => JSON.stringify(item));
				let minusArr = oldStrArr.filter(item => {
					return !newStrArr.includes(item)
				})
				let plusArr = newStrArr.filter(item => {
					return !oldStrArr.includes(item)
				})
				return {
					origin: newValue,
					minus: minusArr.map(item => JSON.parse(item)),
					plus: plusArr.map(item => JSON.parse(item))
				}
			},
			onClick(params) {
				// 调用 service 层的方法
			 	this.ownerInstanceObj.callMethod('onViewClick', params)
			}
		}
	}
</script>

<style lang="scss" scoped>
</style>